#pragma once

#include <glm/glm.hpp>
#include <memory>
#include <vector>

class Bitmap final {
 public:
  struct Pixel {
    uint8_t r = 0;
    uint8_t g = 0;
    uint8_t b = 0;
    uint8_t a = 0;

    Pixel() = default;
    Pixel(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255)
        : r(r), g(g), b(b), a(a) {}

    Pixel(const Pixel &) = default;
    Pixel &operator=(const Pixel &) = default;
  };

  Bitmap(uint32_t width, uint32_t height);
  ~Bitmap() = default;

  void clearColor(Pixel const &color);

  Pixel getPixel(uint32_t x, uint32_t y);

  void setPixel(uint32_t x, uint32_t y, Pixel const &pixel);

  void setPixel(uint32_t x, uint32_t y, glm::vec3 const &pixel);

  void setPixel(uint32_t x, uint32_t y, glm::vec3 const &pixel,
                int32_t samples_per_pixel);

  void writeToFile(const char *file_name);

  uint32_t Width() const { return mWidth; }
  uint32_t Height() const { return mHeight; }
  float PixelRadio() const { return float(mWidth) / float(mHeight); }

  static std::unique_ptr<Bitmap> CreateBitmap(uint32_t width,
                                              float pixel_radio);

 private:
  uint32_t pixelIndex(uint32_t x, uint32_t y);

 private:
  std::vector<Pixel> mPixels;
  uint32_t mWidth;
  uint32_t mHeight;
};